__author__ = 'maikel'

import math
import csv
import generatefeedvector as generate
import pandas as pd
import numpy as np
import json


# CREACIO DEL DATAFRAME
unames = ['id_blog', 'partit_politic', 'nom', 'url']
df = pd.read_table('blogs.dat', sep='::', header=None, names=unames)

data_blogs = {}
invalid_blogs = []

with open('data_blogs.json', 'r') as f:
    data_blogs = json.load(f)

with open('invalid_blogs.json', 'r') as f:
    invalid_blogs = json.load(f)

df = df.drop(invalid_blogs)


def count_blogs(df):
    return len(df.id_blog.unique())


def count_blogs_party(df):
    partits_politics = df.partit_politic.unique()
    series = pd.Series(data=[len(df[df.partit_politic == partit_politic]) for partit_politic in partits_politics],
                       index=partits_politics)
    return series

def count_words(df, data_blogs):
    data = {}
    for blog in data_blogs.values():
        # recorremos las palabras del blog
        for word in blog[1]:
            # Si la palabra no esta en el diccionario, la incluimos
            if word not in data:
                data[word] = {'freq': 0, 'n_cops': 0}
                # sumamos los valores
            data[word]['freq'] += blog[1][word]
            data[word]['n_cops'] += 1
    return data

def count_words_party(df,dicc_text):

    #: Diccionario a retornar tipo enunciado
    diccionari = {}

    #: Partidos politicos que hay
    partits_politics = df.partit_politic.unique()

    for partit_politic in partits_politics:

        #: Por cada partido politico extraemos todos los indices de los blogs que pertenezcan
        # a dicho partido.
        idxBlogs_partitPolitic = df[df.partit_politic == partit_politic].index

        #: Diccionario que contendra todas las palabras que aparecen en los blogs de dicho partido
        diccionari_paraules = {}

        for idxBlog in idxBlogs_partitPolitic:
            #: Extraemos las palabras de un determinado blog
            dict_paraules = dicc_text[str(idxBlog)][1]

            for paraula, numAparicions in dict_paraules.items():
                #: Comprobamos si la palabra ya esta en el diccionario de palabras del partido politico
                if (paraula in diccionari_paraules):
                    #Sumamos numero de apariciones e incrementamos en 1 el
                    #numero de blogs en el que aparece
                    diccionari_paraules[paraula]['freq'] += numAparicions
                    diccionari_paraules[paraula]['n_cops'] += 1
                else:
                    #Incluimos palabra inicializada con el numero de apariciones inicial
                    #y que ha aparecido una vez
                    diccionari_paraules[paraula] = {'freq':numAparicions,'n_cops':1}

        #Al partido politico le asignamos el diccionario de palabras totales de sus blogs.
        diccionari[partit_politic] = diccionari_paraules

    return diccionari

def topNwords(df,words_partits,N):
    #: numero total de blogs
    n_blogs = count_blogs(df);

    #: Partidos politicos que hay
    partits = df.partit_politic.unique()

    #: palabras indiferentes que aparecen muy poco o demasiadas veces
    paraules_importants = {}

    #Aquellas palabras que aparezcan menos del 10% de 121 blogs, o mas del
    #50% de 121 blogs, seran palabras que aparecen en un conjunto muy pequenyo
    #de blogs o que aparecen en la mayoria de blogs, respectivamente
    for paraula in words_partits:
        if (float(words_partits[paraula]['n_cops']) / n_blogs) > 0.1 and (float(words_partits[paraula]['n_cops']) / n_blogs < 0.6):
            paraules_importants[paraula] = words_partits[paraula]['n_cops']

    #: top N paraules importants per a cada partit politic
    paraules_importants_per_partit = {}

    #: paraules de cada partit
    paraules_per_partit = count_words_party(df, data_blogs)

    # Recorremos el diccionario de paraules partits, y por cada partido, tan solo mantenemos las palabras
    # que estan dentro del diccionario de palabras importantes
    for partit in partits:
        #: extraemos las palabras de ese partido
        paraules_partit = paraules_per_partit[partit]

        paraules_importants_per_partit[partit] = sorted([ ( paraules_partit[paraula]['n_cops'], paraula )
                                                   for paraula in paraules_importants
                                                   if paraula in paraules_partit ], reverse=True)[:N]
    return paraules_importants_per_partit

def create_features(data_blogs, top_words):

    diccionari = {}

    #: partidos politicos
    partits = top_words.keys()

    #: N words
    values = top_words.values()
    all_topwords = list(set([values[i][j][1] for i in range(len(values)) for j in range(len(values[i]))]))

    # Iteramos sobre los partidos
    for partit in partits:

        #: diccionario de blog-vector caracteristicos de cada partido
        diccionari_partit = {}

        #: indices de los blogs del partido
        idxBlogs_partit = df[df.partit_politic == partit].index

        for idxBlog in idxBlogs_partit:

            #: todas las palabras del blog
            paraules_blog = data_blogs[str(idxBlog)][1].keys()

            #: vector caracteristico inicialmente a 0, y de longitud igual a all_topWords
            caracteristic = [0] * len(all_topwords)

            # Por cada palabra de las importantes miramos si aparece en el blog
            for idx in range(len(all_topwords)):

                if all_topWords[idx] in paraules_blog:
                    #Si aparece, lo indicamos
                    caracteristic[idx] = 1

            # Juntamos blog con su vector caracteristico
            diccionari_partit[idxBlog] = np.array(caracteristic)

        # Adjuntamos conjunto de blogs junto-vectorCaract a cada partido
        diccionari[partit] = diccionari_partit

    return diccionari

N = 10

top_words = topNwords(df, count_words(df,data_blogs), N)

dict_feat_vector = create_features(data_blogs,top_words)